package com.engine.core.domain;

import com.engine.core.exception.ContainsSqlInjection;
import com.engine.dialect.DialectType;
import org.apache.commons.lang3.StringUtils;

import java.util.Map;

public enum Opt {
    // 等于
    EQ("="),
    // 不等于
    NE("<>"),
    // 大于
    GT(">"),
    // 大于等于
    GE(">="),
    // 小于
    LT("<"),
    // 小于等于
    LE("<="),
    // 包含
    LIKE("like"),

    RLIKE("like"),
    LLIKE("like"),


    NRLIKE("like"),
    NLLIKE("like"),

    // 包含
    NLIKE("not like"),
    //介于
    BETWEEN("between"),
    //不介于
    NBETWEEN(" not between"),
    //在列表中
    IN("in"),
    OR("and"),
    AND("or"),
    //不在列表中
    NIN("not in"),

    NULL("is null"),
    NNULL("is not null"),

    //传参，不参与构建sql
    PARAM("");

    private String dbOper;

     Opt(String dbOper) {
        this.dbOper = dbOper;
    }
    Opt(){

    }

    public String DbOper() {
        return dbOper;
    }

    public String getWhere(String column, String[] paramAlias, String columnAlias, Map<String,String> columnAliasMap,boolean containNull,DialectType dialectType){
        if(StringUtils.isNotBlank(columnAlias)){
            columnAliasMap.put(column,columnAlias);
        }
        ContainsSqlInjection.checkSqlStr(column);
        ContainsSqlInjection.checkSqlStr(columnAlias);
         switch (this){
             case EQ:
             case NE:
             case GT:
             case GE:
             case LT:
             case LE:
                 return dialectType.comonOper(getColumnAlias(column,columnAlias,columnAliasMap),this,paramAlias[0],null,containNull,false);
             case LIKE:
                 return dialectType.like(getColumnAlias(column,columnAlias,columnAliasMap),paramAlias[0],null,false);
             case NLIKE:
                 return dialectType.like(getColumnAlias(column,columnAlias,columnAliasMap),paramAlias[0],null,true);
             case RLIKE:
                 return dialectType.rightLike(getColumnAlias(column,columnAlias,columnAliasMap),paramAlias[0],null,false);
             case NRLIKE:
                 return dialectType.rightLike(getColumnAlias(column,columnAlias,columnAliasMap),paramAlias[0],null,true);
             case LLIKE:
                 return dialectType.leftLike(getColumnAlias(column,columnAlias,columnAliasMap),paramAlias[0],null,false);
             case NLLIKE:{
                 return dialectType.leftLike(getColumnAlias(column,columnAlias,columnAliasMap),paramAlias[0],null,true);
             }
             case IN:
             case NIN:{
                 return getColumnAlias(column,columnAlias,columnAliasMap)+" "+this.dbOper+" (:"+manyParamAlias(paramAlias,true)+") ";
             }
             case BETWEEN:
             case NBETWEEN:{
                 return getColumnAlias(column,columnAlias,columnAliasMap)+" " +this.dbOper+" :"+paramAlias[0]+" and :"+paramAlias[1];
             }
             case NULL:
             case NNULL:{
                 return getColumnAlias(column,columnAlias,columnAliasMap)+" "+this.dbOper;
             }
             case PARAM:
             default:{
                 return "";
             }
         }
    }

    public String getWhere(String column,String[] exps,String[] paramAlias,String columnAlias,Map<String,String> columnAliasMap,boolean containNull,DialectType dialectType){
         if(StringUtils.isNotBlank(columnAlias)){
             columnAliasMap.put(column,columnAlias);
         }
        ContainsSqlInjection.checkSqlStr(column);
        ContainsSqlInjection.checkSqlStr(columnAlias);
        switch (this){
            case EQ:
            case NE:
            case GT:
            case GE:
            case LT:
            case LE:
                return dialectType.comonOper(getColumnAlias(column,columnAlias,columnAliasMap),this,paramAlias[0],exps[0],containNull,false);
            case NLLIKE:
                return dialectType.leftLike(getColumnAlias(column,columnAlias,columnAliasMap),paramAlias[0],exps[0],true);
            case NRLIKE:
                return dialectType.rightLike(getColumnAlias(column,columnAlias,columnAliasMap),paramAlias[0],exps[0],true);
            case LLIKE:
                return dialectType.leftLike(getColumnAlias(column,columnAlias,columnAliasMap),paramAlias[0],exps[0],false);
            case RLIKE:
                return dialectType.rightLike(getColumnAlias(column,columnAlias,columnAliasMap),paramAlias[0],exps[0],false);
            case LIKE:
                return dialectType.like(getColumnAlias(column,columnAlias,columnAliasMap),paramAlias[0],exps[0],false);
            case NLIKE:{
                return dialectType.like(getColumnAlias(column,columnAlias,columnAliasMap),paramAlias[0],exps[0],true);
            }
            case IN:
            case NIN:{
                return getColumnAlias(column,columnAlias,columnAliasMap)+this.dbOper+" ("+manyParamAlias(exps,false)+") ";
            }
            case BETWEEN:
            case NBETWEEN:{
                return getColumnAlias(column,columnAlias,columnAliasMap)+this.dbOper+" " +exps[0]+" and "+exps[0];
            }
            case NULL:
            case NNULL:{
                return getColumnAlias(column,columnAlias,columnAliasMap)+" "+this.dbOper;
            }
            case PARAM:
            default:{
                return "";
            }
        }
    }


    public static Opt getByName(String name){
        Opt r=null;
        for (Opt e:values()) {
            if(e.name().equalsIgnoreCase(name)){
                r=e;
                break;
            }
        }
        return r;
    }

    public static String getColumnAlias(String column,String columnAlias,Map<String,String> columnAliasMap){
         if(StringUtils.isBlank(columnAlias) && !columnAliasMap.containsKey(column)){
               return column;
         }else if(StringUtils.isNotBlank(columnAlias)){
             return columnAlias+"."+column;
         }else{
             return columnAliasMap.get(column)+"."+column;
         }
    }

    private String manyParamAlias(String[] paramAlias,boolean maohao){
         StringBuilder builder=new StringBuilder();
        for (int i = 0; i < paramAlias.length; i++) {
            if(maohao){
                builder.append(":"+paramAlias[i]);
            }
            builder.append(",");
        }
        if(paramAlias.length>0){
            builder.deleteCharAt(builder.length()-1);
        }
        return builder.toString();
    }
}
